home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 1995 #5 & #6
/
Amiga Plus CD - 1995 - No. 5 and 6.iso
/
tex
/
src
/
specialhost
/
dither.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-28
|
8KB
|
239 lines
/* ############### C A U T I O N ################ */
/* */
/* These routines are written for speed, not for readableness. */
/* Read at your own risk, but look also at the object code. */
/* */
/****************************************************************/
extern UBYTE IFFColors[64]; /* gray-values of the 64 IFF-colors */
extern UBYTE HAMColors[16][16][16]; /* gray-values of all 4096 colors */
extern WORD ColorTab[64]; /* the original colormap */
/* this routine unpacks one row of the BitMap */
static void UnPack(struct BitMap *BMin, USHORT Row, USHORT w, UBYTE *UnPacked,
BOOL IsHam)
/* BMin -- the BitMap to be unpacked */
/* Row -- the line to be unpacked */
/* w -- the width of the BitMap (in Pixel) */
/* UnPacked -- the result, should be UBYTE UnPacked[w] */
/* IsHam -- TRUE if picture is HAM */
{
UBYTE *InRow[6], BitMask, Colour, Colour4;
UBYTE r, g, b;
USHORT col;
const ULONG offset = (ULONG)BMin->BytesPerRow * (ULONG)Row;
/* 1st HAM color is always color 0 */
r = ColorTab[0] >> 8 & 0x0F;
g = ColorTab[0] >> 4 & 0x0F;
b = ColorTab[0] >> 0 & 0x0F;
/* init pointers to beginning of row */
switch(BMin->Depth)
{
case 6 : InRow[5] = BMin->Planes[5] + offset;
case 5 : InRow[4] = BMin->Planes[4] + offset;
case 4 : InRow[3] = BMin->Planes[3] + offset;
case 3 : InRow[2] = BMin->Planes[2] + offset;
case 2 : InRow[1] = BMin->Planes[1] + offset;
default : InRow[0] = BMin->Planes[0] + offset;
}
/* 1st bit has mask %10000000 = 0x80 */
BitMask = 0x80;
for(col=0; col<w; col++)
{
Colour = 0;
switch(BMin->Depth)
{
case 6 : if (*InRow[5] & BitMask) Colour |= 0x20; /* set bit 5 */
case 5 : if (*InRow[4] & BitMask) Colour |= 0x10; /* set bit 4 */
case 4 : if (*InRow[3] & BitMask) Colour |= 0x08; /* set bit 3 */
case 3 : if (*InRow[2] & BitMask) Colour |= 0x04; /* set bit 2 */
case 2 : if (*InRow[1] & BitMask) Colour |= 0x02; /* set bit 1 */
default : if (*InRow[0] & BitMask) Colour |= 0x01; /* set bit 0 */
}
/* calculate gray value */
if (IsHam)
{
Colour4 = Colour & 0x0F;
switch (Colour >> 4)
{
case 0 : r = ColorTab[Colour4] >> 8 & 0x0F;
g = ColorTab[Colour4] >> 4 & 0x0F;
b = ColorTab[Colour4] >> 0 & 0x0F;
break;
case 1 : b = Colour4;
break;
case 2 : r = Colour4;
break;
case 3 : g = Colour4;
break;
}
UnPacked[col] = HAMColors[r][g][b];
}
else UnPacked[col] = IFFColors[Colour];
/* advance to next pixel */
BitMask >>= 1;
if (!BitMask)
{
switch(BMin->Depth)
{
case 6 : InRow[5]++;
case 5 : InRow[4]++;
case 4 : InRow[3]++;
case 3 : InRow[2]++;
case 2 : InRow[1]++;
default : InRow[0]++;
}
BitMask = 0x80;
}
}
}
/* this is the great dithering matrix */
/* see c't 3/88 article 'Pixel-Domino' for more details */
static const UBYTE Dither0[16][16] =
{ 0, 128, 32, 160, 8, 136, 40, 168, 2, 130, 34, 162, 10, 138, 42, 170,
192, 64, 224, 96, 200, 72, 232, 104, 194, 66, 226, 98, 202, 74, 234, 106,
48, 176, 16, 144, 56, 184, 24, 152, 50, 178, 18, 146, 58, 186, 26, 154,
240, 112, 208, 80, 248, 120, 216, 88, 242, 114, 210, 82, 250, 122, 218, 90,
12, 140, 44, 172, 4, 132, 36, 164, 14, 142, 46, 174, 6, 134, 38, 166,
204, 76, 236, 108, 196, 68, 228, 100, 206, 78, 238, 110, 198, 70, 230, 102,
60, 188, 28, 156, 52, 180, 20, 148, 62, 190, 30, 158, 54, 182, 22, 150,
252, 124, 220, 92, 244, 116, 212, 84, 254, 126, 222, 94, 246, 118, 214, 86,
3, 131, 35, 163, 11, 139, 43, 171, 1, 129, 33, 161, 9, 137, 41, 169,
195, 67, 227, 99, 203, 75, 235, 107, 193, 65, 225, 97, 201, 73, 233, 105,
51, 179, 19, 147, 59, 187, 27, 155, 49, 177, 17, 145, 57, 185, 25, 153,
243, 115, 211, 83, 251, 123, 219, 91, 241, 113, 209, 81, 249, 121, 217, 89,
15, 143, 47, 175, 7, 135, 39, 167, 13, 141, 45, 173, 5, 133, 37, 165,
207, 79, 239, 111, 199, 71, 231, 103, 205, 77, 237, 109, 197, 69, 229, 101,
63, 191, 31, 159, 55, 183, 23, 151, 61, 189, 29, 157, 53, 181, 21, 149,
255, 127, 223, 95, 247, 119, 215, 87, 253, 125, 221, 93, 245, 117, 213, 85,
};
/* Dither is Dither0 scaled by a factor to save some multiplications */
static ULONG Dither[16][16];
/* an array of bitmasks */
static const UBYTE Bit[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
/* the main dither routine */
/* it is based on extract_one from the FBM graphics package, */
/* but is heavy optimized for speed, like elimanation of */
/* loop invariants, loop unrolling etc. */
/* */
/* PS: if you don't understand it, don't shame */
/* i'm sure, in a few weeks, i'll have difficulties */
/* to understand it myself. ;-> */
void dither(struct BitMap *BMin, USHORT w, struct BitMap * BMout, USHORT ow,
BOOL IsHam)
/* BMin -- the original BitMap */
/* w -- the width of BMin in pixel */
/* BMout -- the new BitMap (to be printed) */
/* ow -- the width of BMout in pixel */
/* IsHam -- TRUE if picture is HAM */
{
USHORT xf, yf, xi, yi, row, col, read;
USHORT OutByte, OutBit;
UBYTE *Temp, *OutRow;
UBYTE BitMask;
UBYTE *InRow1 = NULL;
UBYTE *InRow2 = NULL;
const USHORT outlen = BMout->BytesPerRow;
const USHORT h = BMin->Rows;
const USHORT oh = BMout->Rows;
const ULONG wh = (ULONG)ow * (ULONG)oh;
const USHORT xm = w % ow;
const USHORT xd = w / ow;
const USHORT ym = h % oh;
const USHORT yd = h / oh;
const ULONG d1 = xm * oh;
if ((InRow1 = AllocMem(w, MEMF_PUBLIC)) && (InRow2 = AllocMem(w, MEMF_PUBLIC)))
{
for(row=0; row<16; row++) for(col=0; col<16; col++)
Dither[row][col] = Dither0[row][col] * wh;
UnPack(BMin, 0, w, InRow1, IsHam);
UnPack(BMin, 1, w, InRow2, IsHam);
read = 0;
yf = 0; yi = 0; OutRow = BMout->Planes[0];
for(row=0; row<oh; row++)
{
ULONG b0, b1, c0, c3, d0, d2;
if (yi == read) ;
else if (yi == read+1)
{
Temp = InRow1; InRow1 = InRow2; InRow2 = Temp;
UnPack(BMin, read+2, w, InRow2, IsHam);
read++;
}
else
{
UnPack(BMin, yi , w, InRow1, IsHam);
UnPack(BMin, yi+1, w, InRow2, IsHam);
read = yi;
}
b0 = ow*yf; b1 = wh - b0;
if (!(row % 100)) pline(" work on line %d (from %d lines)", row, oh);
xf = 0; xi = 0; c0 = 0; c3 = 0;
d0 = xm*yf; d2 = ow*yf;
for(col=0; col<ow; col++)
{
OutByte = col >> 3; OutBit = col & 0x07;
BitMask = Bit[OutBit];
if(xi > w-2 || yi > h-2)
{
if((xi == w-1 && yi <= h-1) || (yi == h-1 && xi <= w-1))
{
if (InRow1[xi] < Dither0[row&15][col&15]) OutRow[OutByte] |= BitMask;
}
}
else
{
ULONG dc;
const ULONG c2 = c0 - c3;
dc = InRow1[xi] * (b1-c2);
dc += InRow2[xi] * (b0 - c0);
dc += InRow1[xi+1] * c2;
dc += InRow2[xi+1] * c0;
if (dc < Dither[row&15][col&15]) OutRow[OutByte] |= BitMask;
}
xf += xm; xi += xd; c0 += d0; c3 += d1;
if (xf >= ow)
{
xf -= ow; c0 -= d2; c3 -= wh;
xi ++;
}
}
OutRow += outlen;
yf += ym; yi += yd;
if (yf >= oh)
{
yf -= oh; yi++;
}
}
}
else pline("Sorry! no memory for buffers");
if (InRow1) FreeMem(InRow1, w);
if (InRow2) FreeMem(InRow2, w);
}